下方程式碼片段全部都是擷取自 Secure Code Warrior 線上安全程式培訓平台,因為練習互動時的題目多半不會只有單一個檔案,可能涉及多個檔案、資料夾及多處地方修改,因此我的文章主要是針對最主要的區塊做修改及說明,若有不好理解的地方非常抱歉也還請見諒,也可以實際上去 Secure Code Warrior 玩玩看,搭配著互動,會更有感的學習哦~
EVP_EncryptInit( e_ctx, EVP_aes_128_ccm(), (const unsigned char*)key.c_str(), iv );
//程式碼片段擷取自 Secure Code Warrior 線上安全程式培訓平台
AES aesText( text );
//程式碼片段擷取自 Secure Code Warrior 線上安全程式培訓平台
解釋:高階加密標準(AES-128) 演算法不是密碼保護的最佳選擇。密碼保護必須使用強大的加密,而不是區塊加密。 此外,AES CCM 模式也不是AES演算法的最佳方法,它僅用於加密一些機密資料(如私人簡訊)。
#include <iostream>
#include "argon2.h"
#include "Scrambler.h"
std::string Scrambler::cipher( const std::string text, const std::string salt )
{
const int outLength = 32;
unsigned char out[ outLength ];
const int encodedLength = 128;
char encoded[ encodedLength ];
argon2_type type = Argon2_i;
int result = argon2_hash( 2, 1 << 16, 1,
text.c_str(), text.length(),
salt.c_str(), salt.length(),
out, outLength,
encoded, encodedLength,
type, ARGON2_VERSION_NUMBER);
if( result != ARGON2_OK )
{
std::cout << "Error: " << argon2_error_message( result ) << std::endl;
exit(1);
}
unsigned char hexout[ outLength * 2 + 4 ];
for( int i = 0; i < outLength; i++ )
{
sprintf((char*)(hexout + i * 2), "%02x", out[ i ] );
}
return std::string( reinterpret_cast< const char* >( hexout ) );
}
//程式碼片段擷取自 Secure Code Warrior 線上安全程式培訓平台
解釋:
Argon2是一個強大的雜湊函式,可用於雜湊密碼、金鑰或其他機密資料。Argon2還是一個記憶體硬函式,這意味它比其他雜湊函式使用更多的記憶體。使用此雜湊函式,攻擊者不能使用GPU並行雜湊數百或數千個密碼。這大大增加了攻擊者破解密碼所需的時間。
此外,對於大多數需要認證加密的應用程式,AES GCM模式應被視為優於CCM。由於發生身份驗證,GCM不易受到位翻轉和其他可以針對計數器安裝的攻擊
byte digest[ CryptoPP::Weak::MD5::DIGESTSIZE ];
CryptoPP::Weak::MD5 hash;
hash.CalculateDigest( digest, (const byte*)word.c_str(), word.length() );
CryptoPP::HexEncoder encoder;
string encodedWord;
encoder.Attach( new CryptoPP::StringSink( encodedWord ) );
encoder.Put( digest, sizeof(digest) );
encoder.MessageEnd();
return encodedWord;
//程式碼片段擷取自 Secure Code Warrior 線上安全程式培訓平台
解釋:MD5被認為產生的雜湊密碼不安全
把encode-controller整份檔案:
#include "encode-controller.hpp"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <string>
#include <vector>
#include "../cryptopp810/md5.h"
using namespace std;
#define CRYPTOPP_ENABLE_NAMESPACE_WEAK 1
EncodeController::EncodeController()
{ }
string EncodeController::EncodeAlgorithm(string word)
{
byte digest[ CryptoPP::Weak::MD5::DIGESTSIZE ];
CryptoPP::Weak::MD5 hash;
hash.CalculateDigest( digest, (const byte*)word.c_str(), word.length() );
CryptoPP::HexEncoder encoder;
string encodedWord;
encoder.Attach( new CryptoPP::StringSink( encodedWord ) );
encoder.Put( digest, sizeof(digest) );
encoder.MessageEnd();
return encodedWord;
}
bool EncodeController::VerifyPassword(string password, string encoded)
{
bool status = false;
string encodedPass = EncodeAlgorithm(password);
if(encodedPass.compare(encoded)==0)
status = true;
return status;
}
//程式碼片段擷取自 Secure Code Warrior 線上安全程式培訓平台
改成:
#include "encode-controller.hpp"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <string>
#include <vector>
#include <openssl/rand.h>
#include "../argon2/include/argon2.h"
#define HASHLEN 32
#define SALTLEN 16
EncodeController::EncodeController()
{ }
std::string EncodeController::EncodeAlgorithm(std::string word)
{
std::string encodedWord;
char * PWD = new char [word.length()+1];
strncpy (PWD, word.c_str(), word.length()+1);
uint8_t hash1[HASHLEN];
uint8_t hash2[HASHLEN];
uint8_t salt[SALTLEN];
RAND_bytes(salt, SALTLEN);
uint8_t *pwd = (uint8_t *)strdup(PWD);
uint32_t pwdlen = strlen((char *)pwd);
uint32_t t_cost = 2; // 1-pass computation
uint32_t m_cost = (1<<16); // 64 mebibytes memory usage
uint32_t parallelism = 1; // number of threads and lanes
// high-level API
argon2i_hash_raw(t_cost, m_cost, parallelism, pwd, pwdlen, salt, SALTLEN, hash1, HASHLEN);
free(pwd);
delete [] PWD;
for( int i=0; i<HASHLEN; ++i )
encodedWord+=hash1[i];
return encodedWord;
}
bool EncodeController::VerifyPassword(std::string password, std::string encoded)
{
bool status = false;
char * PWD = new char [password.length()+1];
char * hashed = new char [encoded.length()+1];
strncpy (PWD, password.c_str(), password.length()+1);
strcpy (hashed, encoded.c_str(), encoded.length()+1);
int vp = argon2i_verify(hashed, PWD, strlen(PWD));
if(ARGON2_OK != vp) {
printf("Error: %s\n", argon2_error_message(vp));
exit(1);
}
else
status = true;
delete [] PWD;
delete [] hashed;
return status;
}
//程式碼片段擷取自 Secure Code Warrior 線上安全程式培訓平台
並刪除md5.cpp和md5.h兩個檔案
解釋:雜湊密碼的絕佳替代方案是使用Argon2演算法,因為它實現了防止GPU破解和側通道攻擊。
(我一開始選改成sha256和sha1的都跟我說是弱演算法)